#include <d3d9.h>
#include <d3dx9.h>
#include "Cube.h"
#include "Face.h"
#include "Constants.h"

// Constructor
Minicraft::Cube::Cube(){}

Minicraft::Cube::Cube(D3DXMATRIX worldMatrix)
{
	this->worldTransformation = worldMatrix;
	this->visible = true;
	this->Initalize();
}

// Deconstructor
Minicraft::Cube::~Cube()
{
	// delete the cube's transformation matrix and each of it's faces.
	for (int x = 0; x < Minicraft::Cube::NUM_OF_FACES; x++)
		delete this->cubeFaces[x];
}

// Gets whether or not this object will render.
bool Minicraft::Cube::GetVisible()
{
	return this->visible;
}

// Sets whether or not all the faces of this Cube will render.
void Minicraft::Cube::SetVisible(bool visible)
{
	this->visible = visible;
	for (int x = 0; x < this->NUM_OF_FACES; x++)
		this->cubeFaces[x]->SetVisible(visible);
}

// Gets the visibility of a single face of this Cube.
bool Minicraft::Cube::GetFaceVisible(enum Minicraft::CubeFaces::e face)
{
	switch(face)
	{
	case(Minicraft::CubeFaces::Top):
		return cubeFaces[0]->GetVisible();
	case(Minicraft::CubeFaces::Botton):
		return cubeFaces[1]->GetVisible();
	case(Minicraft::CubeFaces::North):
		return cubeFaces[2]->GetVisible();
	case(Minicraft::CubeFaces::East):
		return cubeFaces[3]->GetVisible();
	case(Minicraft::CubeFaces::South):
		return cubeFaces[4]->GetVisible();
	case(Minicraft::CubeFaces::West):
		return cubeFaces[5]->GetVisible();
	default:
		// invalid value
		return false;
	}
}

// Sets the visibility of a single fface of this cube.
void Minicraft::Cube::SetFaceVisible(enum Minicraft::CubeFaces::e face, bool visible)
{
	switch(face)
	{
	case(Minicraft::CubeFaces::Top):
		cubeFaces[0]->SetVisible(visible);
		break;
	case(Minicraft::CubeFaces::Botton):
		cubeFaces[1]->SetVisible(visible);
		break;
	case(Minicraft::CubeFaces::North):
		cubeFaces[2]->SetVisible(visible);
		break;
	case(Minicraft::CubeFaces::East):
		cubeFaces[3]->SetVisible(visible);
		break;
	case(Minicraft::CubeFaces::South):
		cubeFaces[4]->SetVisible(visible);
		break;
	case(Minicraft::CubeFaces::West):
		cubeFaces[5]->SetVisible(visible);
		break;
	default:
		// invalid value
		break;
	}
}

void Minicraft::Cube::SetType(Minicraft::CubeType::e type)
{
	switch (type)
	{
	case Minicraft::CubeType::Air:
		this->SetVisible(false);
		break;
	case Minicraft::CubeType::Grass:
		this->SetToGrass();
		break;
	case Minicraft::CubeType::Dirt:
		this->SetToDirt();
		break;
	default:
		this->SetToDirt();
		break;
	}
}

void Minicraft::Cube::SetToGrass()
{
	this->cubeFaces[Minicraft::CubeFaces::North]->SetTexture(Minicraft::Textures::TextureList::grass_side);
	this->cubeFaces[Minicraft::CubeFaces::South]->SetTexture(Minicraft::Textures::TextureList::grass_side);
	this->cubeFaces[Minicraft::CubeFaces::East]->SetTexture(Minicraft::Textures::TextureList::grass_side);
	this->cubeFaces[Minicraft::CubeFaces::West]->SetTexture(Minicraft::Textures::TextureList::grass_side);
	this->cubeFaces[Minicraft::CubeFaces::Top]->SetTexture(Minicraft::Textures::TextureList::grass);
	this->cubeFaces[Minicraft::CubeFaces::Botton]->SetTexture(Minicraft::Textures::TextureList::dirt);
}

void Minicraft::Cube::SetToDirt()
{
	for (int x = 0; x < Minicraft::Cube::NUM_OF_FACES; x++)
		this->cubeFaces[x]->SetTexture(Minicraft::Textures::TextureList::dirt);
}

// Creates all the faces of this cube.
void Minicraft::Cube::Initalize()
{
	for (int x = 0; x < Minicraft::Cube::NUM_OF_FACES; x++)
	{		
		D3DXMATRIX faceTranslation = D3DXMATRIX();
		D3DXMATRIX faceRotation = D3DXMATRIX();
		float size = Minicraft::Constants::FACESIZE;

		// create the transformations for the face relative to the center of the cube
		switch(x)
		{
		case(Minicraft::CubeFaces::Top):
			D3DXMatrixTranslation(&faceTranslation, 0.0f, size, 0.0f);
			D3DXMatrixRotationX(&faceRotation, D3DXToRadian(90.0f));
			break;
		case(Minicraft::CubeFaces::Botton):
			D3DXMatrixTranslation(&faceTranslation, 0.0f, -size, 0.0f);
			D3DXMatrixRotationX(&faceRotation, D3DXToRadian(270.0f));
			break;
		case(Minicraft::CubeFaces::South):
			D3DXMatrixTranslation(&faceTranslation, 0.0f, 0.0f, size);
			D3DXMatrixRotationY(&faceRotation, D3DXToRadian(180.0f));
			break;
		case(Minicraft::CubeFaces::North):
			D3DXMatrixTranslation(&faceTranslation, 0.0f, 0.0f, -size);
			D3DXMatrixRotationY(&faceRotation, D3DXToRadian(0.0f));
			break;
		case(Minicraft::CubeFaces::East):
			D3DXMatrixTranslation(&faceTranslation, -size, 0.0f, 0.0f);
			D3DXMatrixRotationY(&faceRotation, D3DXToRadian(90.0f));
			break;
		case(Minicraft::CubeFaces::West):
			D3DXMatrixTranslation(&faceTranslation, size, 0.0f, 0.0f);
			D3DXMatrixRotationY(&faceRotation, D3DXToRadian(270.0f));
			break;
		default:
			// this best not happen
			D3DXMatrixIdentity(&faceTranslation);
			D3DXMatrixIdentity(&faceRotation);
			break;
		}

		this->cubeFaces[x] = new Face( (faceRotation * faceTranslation * this->worldTransformation) );
	}
}

// Draws all visible faces of this cube.
void Minicraft::Cube::Draw()
{
	for (int x = 0; x < Minicraft::Cube::NUM_OF_FACES; x++)
		this->cubeFaces[x]->Draw();
}